API’s

O que são API’s?

Definição

  • API é a sigla para Application Programming Interface.

  • É uma interface de comunicação que um sistema oferece para que outros sistemas acessem suas funções, dados, serviços e recursos.

  • Possibilitam utilizar funções de um aplicativo dentro de outro, facilitando o trabalho dos desenvolvedores.

  • Permitem o acesso a dados, sem a necessidade de raspagem de superfície (scraping) ou coleta manual.

Tipos de API

API’s privadas

São internas de uma empresa e são usadas apenas para conectar sistemas e dados dentro da empresa.

API’s públicas

São abertas ao público e podem ser usadas por qualquer pessoa.

Pode ou não haver alguma autorização e/ou custo associado a esses tipos de APIs.

API’s de parceiros

Acessíveis apenas por desenvolvedores externos autorizados, em nome de empresas parceiras.

Arquitetura e comunicação

  • REST (Representational State Transfer): simples e intuitiva, escalável e amplamente adotada

  • SOAP (Simple Object Access Protocol): padrões rigorosos, maior segurança

  • GraphQL: complexa, flexível e eficiente, permite a requisição de dados específicos

  • RPC (Remote Procedure Call): uso procedural simples, mas pode ser complexa para gerenciamento de recursos

Como funcionam?

Visão geral

  • As APIs funcionam através de um protocolo, um conjunto de instruções, padrões e regras que definem como os sistemas devem se comunicar.

  • Elas estabelecem métodos de requisição, formatos de dados a serem recebidos ou retornados, autenticação e autorização de acesso, entre outros aspectos técnicos.

  • Quando um software utiliza uma API, ele envia uma requisição seguindo as diretrizes estabelecidas pela interface, e em resposta recebe os dados ou realiza as ações desejadas.

Etapas

  1. Uma requisição é enviada ao sistema que disponibiliza uma API (servidor) por um cliente (que pode ser um navegador, um aplicativo móvel ou outro servidor). Geralmente segue o protocolo HTTP (Hypertext Transfer Protocol).

  2. O servidor faz o processamento da requisição, que pode envolver uma consulta a uma base de dados ou acesso a outras funcionalidades.

  3. O servidor envia uma resposta ao cliente. Geralmente inclui um código de status, indicativo de sucesso ou falha na requisição, e os dados solicitados.

Métodos de requisição HTTP

Os principais métodos de requisição são:

  • get: requisição para obter, visualizar ou extrair dados;

  • post: requisição para criar ou enviar novos dados;

  • put: requisição para editar ou atualizar dados;

  • delete: requisição para remover dados.

Códigos de Status HTTP

  • 1xx (Informacional): Requisição recebida, processo em andamento.

  • 2xx (Exitoso): Requisição recebida com sucesso e aceita.

  • 3xx (Redirecionamento): É necessário tomar alguma medida para completar a requisição.

  • 4xx (Erro de Cliente): A requisição apresenta problemas de sintaxe ou não pôde ser completada por algum motivo. (401, 404)

  • 5xx (Erro de Servidor): O servidor falhou em completar uma requisição válida.

Requisições e chaves de acesso

  • É comum que alguns sistemas exijam o uso de chaves para limitar e controlar a quantidade de requisições de acesso.

  • Essa medida visa a segurança do próprio sistema, garantindo a sua disponibilidade e evitando por exemplo ataques de negação de serviço (DoS).

Requisições e chaves de acesso

  • Além de ajudar a detectar atividades suspeitas, as chaves de acesso também servem para identificar, monitorar e registrar quem consome a API, a fim de obter insights a respeito dos padrões de uso do serviço e aprimorá-lo.

  • Alguns sistemas monetizam o consumo das API’s.

  • Ainda assim, alguns sistemas permitem que sejam feitas requisições keyless.

Endpoints

  • Endpoints são funções ou recursos da API que, dado sua estrutura hierárquica (aninhada, ou em árvore), podem ser acessadas diretamente pelo sistema cliente.

  • Para acessar um endpoint específico dentro de uma API, basta utilizarmos o URL (Uniform Resource Locator) principal da API seguido do caminho correspondente a esse endpoint.

Endpoints

Placeholders

É comum utilizarmos chaves {} como placeholders ao nos referirmos a endpoints.

Parâmetros de consulta

Podemos, ainda utilizar parâmetros simples de consulta para filtrar os resultados de uma requisição. Ex.:

/usuarios?sexo=masculino

Operadores: &, |

JSON (JavaScript Object Notation)

  • Padrão de indústria
  • Interoperabilidade
  • Legibilidade
  • Parseável
  • Simples, leve e eficiente
  • Vulnerabilidade (DoS, XSS, vazamentos)

JSON vs. XML

JSON XML
Vantagens Sintaxe, legibilidade
Tipos de dados
Performance
Interoperabilidade
Validação, integridade e consistência
Inclusão de metadados
Robustez
Desvantagens Ausência de metadados
Não comentável
Vulnerabilidade
Verbosidade
Lentidão e maior uso de recursos

JSON vs. CSV

JSON XML
Vantagens Suporte a estruturas aninhadas/hierarquizadas
Tipos de dados e estruturas
Simplicidade e legibilidade
Leveza e eficiência
Compatibilidade
Desvantagens Legibilidade para dados simples, tabulares
Tamanho, sintaxe adicional
Inadequado para dados complexos
Inconsistência (encoding)

Exemplos de consumo de API usando R

Vejamos alguns exemplos de como interagir com APIs diferentes utilizando linguagem R.

PokéAPI (Keyless)

Temos que pegar!

if (!require("httr", character.only = TRUE)) {
  install.packages("httr")}
if (!require("jsonlite", character.only = TRUE)) {
  install.packages("jsonlite")}

library(httr)
library(jsonlite)

#Construir URL
 
pokemon_base <- "https://pokeapi.co/api/v2/pokemon/"

pokemon_endpoint <- ""

pokemon_url <- base::paste0(pokemon_base, pokemon_endpoint)

pokemon_url
[1] "https://pokeapi.co/api/v2/pokemon/"

Requisição (API call)

pokemon_call <- httr::GET(pokemon_url)

Retorna uma lista! Nesse caso, com 10 elementos, sendo os de interesse: “url”, “status_code” e “content”.

Visualizar a resposta da API

Para termos uma visão geral resumida do objeto, podemos rodar:

pokemon_call
Response [https://pokeapi.co/api/v2/pokemon/]
  Date: 2024-06-24 08:46
  Status: 200
  Content-Type: application/json; charset=utf-8
  Size: 1.42 kB

Vamos tentar dar uma olhada no conteúdo retornado:

pokemon_call$content
   [1] 7b 22 63 6f 75 6e 74 22 3a 31 33 30 32 2c 22 6e 65 78 74 22 3a 22 68 74
  [25] 74 70 73 3a 2f 2f 70 6f 6b 65 61 70 69 2e 63 6f 2f 61 70 69 2f 76 32 2f
  [49] 70 6f 6b 65 6d 6f 6e 2f 3f 6f 66 66 73 65 74 3d 32 30 26 6c 69 6d 69 74
  [73] 3d 32 30 22 2c 22 70 72 65 76 69 6f 75 73 22 3a 6e 75 6c 6c 2c 22 72 65
  [97] 73 75 6c 74 73 22 3a 5b 7b 22 6e 61 6d 65 22 3a 22 62 75 6c 62 61 73 61
 [121] 75 72 22 2c 22 75 72 6c 22 3a 22 68 74 74 70 73 3a 2f 2f 70 6f 6b 65 61
 [145] 70 69 2e 63 6f 2f 61 70 69 2f 76 32 2f 70 6f 6b 65 6d 6f 6e 2f 31 2f 22
 [169] 7d 2c 7b 22 6e 61 6d 65 22 3a 22 69 76 79 73 61 75 72 22 2c 22 75 72 6c
 [193] 22 3a 22 68 74 74 70 73 3a 2f 2f 70 6f 6b 65 61 70 69 2e 63 6f 2f 61 70
 [217] 69 2f 76 32 2f 70 6f 6b 65 6d 6f 6e 2f 32 2f 22 7d 2c 7b 22 6e 61 6d 65
 [241] 22 3a 22 76 65 6e 75 73 61 75 72 22 2c 22 75 72 6c 22 3a 22 68 74 74 70
 [265] 73 3a 2f 2f 70 6f 6b 65 61 70 69 2e 63 6f 2f 61 70 69 2f 76 32 2f 70 6f
 [289] 6b 65 6d 6f 6e 2f 33 2f 22 7d 2c 7b 22 6e 61 6d 65 22 3a 22 63 68 61 72
 [313] 6d 61 6e 64 65 72 22 2c 22 75 72 6c 22 3a 22 68 74 74 70 73 3a 2f 2f 70
 [337] 6f 6b 65 61 70 69 2e 63 6f 2f 61 70 69 2f 76 32 2f 70 6f 6b 65 6d 6f 6e
 [361] 2f 34 2f 22 7d 2c 7b 22 6e 61 6d 65 22 3a 22 63 68 61 72 6d 65 6c 65 6f
 [385] 6e 22 2c 22 75 72 6c 22 3a 22 68 74 74 70 73 3a 2f 2f 70 6f 6b 65 61 70
 [409] 69 2e 63 6f 2f 61 70 69 2f 76 32 2f 70 6f 6b 65 6d 6f 6e 2f 35 2f 22 7d
 [433] 2c 7b 22 6e 61 6d 65 22 3a 22 63 68 61 72 69 7a 61 72 64 22 2c 22 75 72
 [457] 6c 22 3a 22 68 74 74 70 73 3a 2f 2f 70 6f 6b 65 61 70 69 2e 63 6f 2f 61
 [481] 70 69 2f 76 32 2f 70 6f 6b 65 6d 6f 6e 2f 36 2f 22 7d 2c 7b 22 6e 61 6d
 [505] 65 22 3a 22 73 71 75 69 72 74 6c 65 22 2c 22 75 72 6c 22 3a 22 68 74 74
 [529] 70 73 3a 2f 2f 70 6f 6b 65 61 70 69 2e 63 6f 2f 61 70 69 2f 76 32 2f 70
 [553] 6f 6b 65 6d 6f 6e 2f 37 2f 22 7d 2c 7b 22 6e 61 6d 65 22 3a 22 77 61 72
 [577] 74 6f 72 74 6c 65 22 2c 22 75 72 6c 22 3a 22 68 74 74 70 73 3a 2f 2f 70
 [601] 6f 6b 65 61 70 69 2e 63 6f 2f 61 70 69 2f 76 32 2f 70 6f 6b 65 6d 6f 6e
 [625] 2f 38 2f 22 7d 2c 7b 22 6e 61 6d 65 22 3a 22 62 6c 61 73 74 6f 69 73 65
 [649] 22 2c 22 75 72 6c 22 3a 22 68 74 74 70 73 3a 2f 2f 70 6f 6b 65 61 70 69
 [673] 2e 63 6f 2f 61 70 69 2f 76 32 2f 70 6f 6b 65 6d 6f 6e 2f 39 2f 22 7d 2c
 [697] 7b 22 6e 61 6d 65 22 3a 22 63 61 74 65 72 70 69 65 22 2c 22 75 72 6c 22
 [721] 3a 22 68 74 74 70 73 3a 2f 2f 70 6f 6b 65 61 70 69 2e 63 6f 2f 61 70 69
 [745] 2f 76 32 2f 70 6f 6b 65 6d 6f 6e 2f 31 30 2f 22 7d 2c 7b 22 6e 61 6d 65
 [769] 22 3a 22 6d 65 74 61 70 6f 64 22 2c 22 75 72 6c 22 3a 22 68 74 74 70 73
 [793] 3a 2f 2f 70 6f 6b 65 61 70 69 2e 63 6f 2f 61 70 69 2f 76 32 2f 70 6f 6b
 [817] 65 6d 6f 6e 2f 31 31 2f 22 7d 2c 7b 22 6e 61 6d 65 22 3a 22 62 75 74 74
 [841] 65 72 66 72 65 65 22 2c 22 75 72 6c 22 3a 22 68 74 74 70 73 3a 2f 2f 70
 [865] 6f 6b 65 61 70 69 2e 63 6f 2f 61 70 69 2f 76 32 2f 70 6f 6b 65 6d 6f 6e
 [889] 2f 31 32 2f 22 7d 2c 7b 22 6e 61 6d 65 22 3a 22 77 65 65 64 6c 65 22 2c
 [913] 22 75 72 6c 22 3a 22 68 74 74 70 73 3a 2f 2f 70 6f 6b 65 61 70 69 2e 63
 [937] 6f 2f 61 70 69 2f 76 32 2f 70 6f 6b 65 6d 6f 6e 2f 31 33 2f 22 7d 2c 7b
 [961] 22 6e 61 6d 65 22 3a 22 6b 61 6b 75 6e 61 22 2c 22 75 72 6c 22 3a 22 68
 [985] 74 74 70 73 3a 2f 2f 70 6f 6b 65 61 70 69 2e 63 6f 2f 61 70 69 2f 76 32
[1009] 2f 70 6f 6b 65 6d 6f 6e 2f 31 34 2f 22 7d 2c 7b 22 6e 61 6d 65 22 3a 22
[1033] 62 65 65 64 72 69 6c 6c 22 2c 22 75 72 6c 22 3a 22 68 74 74 70 73 3a 2f
[1057] 2f 70 6f 6b 65 61 70 69 2e 63 6f 2f 61 70 69 2f 76 32 2f 70 6f 6b 65 6d
[1081] 6f 6e 2f 31 35 2f 22 7d 2c 7b 22 6e 61 6d 65 22 3a 22 70 69 64 67 65 79
[1105] 22 2c 22 75 72 6c 22 3a 22 68 74 74 70 73 3a 2f 2f 70 6f 6b 65 61 70 69
[1129] 2e 63 6f 2f 61 70 69 2f 76 32 2f 70 6f 6b 65 6d 6f 6e 2f 31 36 2f 22 7d
[1153] 2c 7b 22 6e 61 6d 65 22 3a 22 70 69 64 67 65 6f 74 74 6f 22 2c 22 75 72
[1177] 6c 22 3a 22 68 74 74 70 73 3a 2f 2f 70 6f 6b 65 61 70 69 2e 63 6f 2f 61
[1201] 70 69 2f 76 32 2f 70 6f 6b 65 6d 6f 6e 2f 31 37 2f 22 7d 2c 7b 22 6e 61
[1225] 6d 65 22 3a 22 70 69 64 67 65 6f 74 22 2c 22 75 72 6c 22 3a 22 68 74 74
[1249] 70 73 3a 2f 2f 70 6f 6b 65 61 70 69 2e 63 6f 2f 61 70 69 2f 76 32 2f 70
[1273] 6f 6b 65 6d 6f 6e 2f 31 38 2f 22 7d 2c 7b 22 6e 61 6d 65 22 3a 22 72 61
[1297] 74 74 61 74 61 22 2c 22 75 72 6c 22 3a 22 68 74 74 70 73 3a 2f 2f 70 6f
[1321] 6b 65 61 70 69 2e 63 6f 2f 61 70 69 2f 76 32 2f 70 6f 6b 65 6d 6f 6e 2f
[1345] 31 39 2f 22 7d 2c 7b 22 6e 61 6d 65 22 3a 22 72 61 74 69 63 61 74 65 22
[1369] 2c 22 75 72 6c 22 3a 22 68 74 74 70 73 3a 2f 2f 70 6f 6b 65 61 70 69 2e
[1393] 63 6f 2f 61 70 69 2f 76 32 2f 70 6f 6b 65 6d 6f 6e 2f 32 30 2f 22 7d 5d
[1417] 7d

Parece que os dados ainda estão inacessíveis. Aqui, obtemos os dados binários do arquivo em formato hexadecimal.

Agora, vamos converter esses binários em string para ver o conteúdo do arquivo json.

pokemon_content <- httr::content(pokemon_call, as = "text")

pokemon_content
[1] "{\"count\":1302,\"next\":\"https://pokeapi.co/api/v2/pokemon/?offset=20&limit=20\",\"previous\":null,\"results\":[{\"name\":\"bulbasaur\",\"url\":\"https://pokeapi.co/api/v2/pokemon/1/\"},{\"name\":\"ivysaur\",\"url\":\"https://pokeapi.co/api/v2/pokemon/2/\"},{\"name\":\"venusaur\",\"url\":\"https://pokeapi.co/api/v2/pokemon/3/\"},{\"name\":\"charmander\",\"url\":\"https://pokeapi.co/api/v2/pokemon/4/\"},{\"name\":\"charmeleon\",\"url\":\"https://pokeapi.co/api/v2/pokemon/5/\"},{\"name\":\"charizard\",\"url\":\"https://pokeapi.co/api/v2/pokemon/6/\"},{\"name\":\"squirtle\",\"url\":\"https://pokeapi.co/api/v2/pokemon/7/\"},{\"name\":\"wartortle\",\"url\":\"https://pokeapi.co/api/v2/pokemon/8/\"},{\"name\":\"blastoise\",\"url\":\"https://pokeapi.co/api/v2/pokemon/9/\"},{\"name\":\"caterpie\",\"url\":\"https://pokeapi.co/api/v2/pokemon/10/\"},{\"name\":\"metapod\",\"url\":\"https://pokeapi.co/api/v2/pokemon/11/\"},{\"name\":\"butterfree\",\"url\":\"https://pokeapi.co/api/v2/pokemon/12/\"},{\"name\":\"weedle\",\"url\":\"https://pokeapi.co/api/v2/pokemon/13/\"},{\"name\":\"kakuna\",\"url\":\"https://pokeapi.co/api/v2/pokemon/14/\"},{\"name\":\"beedrill\",\"url\":\"https://pokeapi.co/api/v2/pokemon/15/\"},{\"name\":\"pidgey\",\"url\":\"https://pokeapi.co/api/v2/pokemon/16/\"},{\"name\":\"pidgeotto\",\"url\":\"https://pokeapi.co/api/v2/pokemon/17/\"},{\"name\":\"pidgeot\",\"url\":\"https://pokeapi.co/api/v2/pokemon/18/\"},{\"name\":\"rattata\",\"url\":\"https://pokeapi.co/api/v2/pokemon/19/\"},{\"name\":\"raticate\",\"url\":\"https://pokeapi.co/api/v2/pokemon/20/\"}]}"

Retorna os dados em formato de texto, mas ainda truncado.

Precisamos converter esse string json em uma tabela. Para isso, lançamos mão da função fromJSON() do jsonlite.

pokemonJSON <- jsonlite::fromJSON(pokemon_content, flatten = TRUE)

pokemonJSON
$count
[1] 1302

$`next`
[1] "https://pokeapi.co/api/v2/pokemon/?offset=20&limit=20"

$previous
NULL

$results
         name                                   url
1   bulbasaur  https://pokeapi.co/api/v2/pokemon/1/
2     ivysaur  https://pokeapi.co/api/v2/pokemon/2/
3    venusaur  https://pokeapi.co/api/v2/pokemon/3/
4  charmander  https://pokeapi.co/api/v2/pokemon/4/
5  charmeleon  https://pokeapi.co/api/v2/pokemon/5/
6   charizard  https://pokeapi.co/api/v2/pokemon/6/
7    squirtle  https://pokeapi.co/api/v2/pokemon/7/
8   wartortle  https://pokeapi.co/api/v2/pokemon/8/
9   blastoise  https://pokeapi.co/api/v2/pokemon/9/
10   caterpie https://pokeapi.co/api/v2/pokemon/10/
11    metapod https://pokeapi.co/api/v2/pokemon/11/
12 butterfree https://pokeapi.co/api/v2/pokemon/12/
13     weedle https://pokeapi.co/api/v2/pokemon/13/
14     kakuna https://pokeapi.co/api/v2/pokemon/14/
15   beedrill https://pokeapi.co/api/v2/pokemon/15/
16     pidgey https://pokeapi.co/api/v2/pokemon/16/
17  pidgeotto https://pokeapi.co/api/v2/pokemon/17/
18    pidgeot https://pokeapi.co/api/v2/pokemon/18/
19    rattata https://pokeapi.co/api/v2/pokemon/19/
20   raticate https://pokeapi.co/api/v2/pokemon/20/

Inicialmente, obtemos uma lista

Se explorarmos qualquer um dos objetos pokemonJSON, notaremos que o que nos interessa está localizado dentro de results.

pokemonJSON$results
         name                                   url
1   bulbasaur  https://pokeapi.co/api/v2/pokemon/1/
2     ivysaur  https://pokeapi.co/api/v2/pokemon/2/
3    venusaur  https://pokeapi.co/api/v2/pokemon/3/
4  charmander  https://pokeapi.co/api/v2/pokemon/4/
5  charmeleon  https://pokeapi.co/api/v2/pokemon/5/
6   charizard  https://pokeapi.co/api/v2/pokemon/6/
7    squirtle  https://pokeapi.co/api/v2/pokemon/7/
8   wartortle  https://pokeapi.co/api/v2/pokemon/8/
9   blastoise  https://pokeapi.co/api/v2/pokemon/9/
10   caterpie https://pokeapi.co/api/v2/pokemon/10/
11    metapod https://pokeapi.co/api/v2/pokemon/11/
12 butterfree https://pokeapi.co/api/v2/pokemon/12/
13     weedle https://pokeapi.co/api/v2/pokemon/13/
14     kakuna https://pokeapi.co/api/v2/pokemon/14/
15   beedrill https://pokeapi.co/api/v2/pokemon/15/
16     pidgey https://pokeapi.co/api/v2/pokemon/16/
17  pidgeotto https://pokeapi.co/api/v2/pokemon/17/
18    pidgeot https://pokeapi.co/api/v2/pokemon/18/
19    rattata https://pokeapi.co/api/v2/pokemon/19/
20   raticate https://pokeapi.co/api/v2/pokemon/20/

Acessar os dados de cada pokémon

Uma maneira seria alterar a URL base, adicionando endpoints:

pokemon_url <- "https://pokeapi.co/api/v2/pokemon/{endpoint}"

Nesse sentido, separar a base do URL dos endpoints é muito conveniente.

Por exemplo, podemos usar essa API para obtermos os stats do Growlithe:

pokemon_base <- "https://pokeapi.co/api/v2/pokemon/"

growlithe_endpoint <- "58"

growlithe_url <- base::paste0(pokemon_base, growlithe_endpoint)

growlithe_call <- httr::GET(growlithe_url)

growlithe_content <- httr::content(growlithe_call, as = "text")

growlithe_JSON <- jsonlite::fromJSON(growlithe_content, flatten = TRUE)

growlithe_stats <- data.frame(growlithe_JSON$stats)

growlithe_stats

  base_stat effort       stat.name                          stat.url
1        55      0              hp https://pokeapi.co/api/v2/stat/1/
2        70      1          attack https://pokeapi.co/api/v2/stat/2/
3        45      0         defense https://pokeapi.co/api/v2/stat/3/
4        70      0  special-attack https://pokeapi.co/api/v2/stat/4/
5        50      0 special-defense https://pokeapi.co/api/v2/stat/5/
6        60      0           speed https://pokeapi.co/api/v2/stat/6/

Aplicações

https://pokemoncries.com/

API OpenWeather

Obtendo a latitude e longitude da cidade

Utilizaremos Brasília como exemplo

url <- base::paste0("https://api.openweathermap.org/geo/1.0/direct?q=Brasília&appid=", key)

loc <- httr::GET(url)

loc$status_code
[1] 200

Com base no código de status, verificamos que a requisição foi aceita.

Conversão do conteúdo

[1] "[{\"name\":\"Brasília\",\"local_names\":{\"vi\":\"Brasilia\",\"sv\":\"Brasília\",\"ia\":\"Brasilia\",\"dv\":\"ބްރަސީލިއާ\",\"qu\":\"Brasilia\",\"he\":\"בראזיליא\",\"or\":\"ବ୍ରାସିଲିଆ\",\"ta\":\"பிரசிலியா\",\"gn\":\"Brasilia\",\"hr\":\"Brazilija\",\"ur\":\"براسیلیا\",\"et\":\"Brasília\",\"yo\":\"Bràsílíà\",\"no\":\"Brasília\",\"oc\":\"Brasília\",\"lv\":\"Brazilja\",\"ce\":\"Бразилиа\",\"rm\":\"Brasilia\",\"sk\":\"Brazília\",\"jv\":\"Brasilia\",\"ru\":\"Бразилиа\",\"ab\":\"Бразилиа\",\"kn\":\"ಬ್ರಾಸಿಲ್ಯಾ\",\"os\":\"Бразилиа\",\"tt\":\"Бразилиа\",\"zh\":\"巴西利亚\",\"ie\":\"Brasilia\",\"sq\":\"Brazilia\",\"az\":\"Brazilia\",\"th\":\"บราซีเลีย\",\"hy\":\"Բրազիլիա\",\"cv\":\"Бразилиа\",\"bs\":\"Brazilija\",\"io\":\"Brasilia\",\"pl\":\"Brasília\",\"am\":\"ብራዚሊያ\",\"sw\":\"Brasilia\",\"sh\":\"Brazilija\",\"tg\":\"Бразилиа\",\"ka\":\"ბრაზილია\",\"sr\":\"Бразилија\",\"ht\":\"Brazilia\",\"gl\":\"Brasilia\",\"pa\":\"ਬ੍ਰਾਜ਼ੀਲੀਆ\",\"es\":\"Brasilia\",\"ko\":\"브라질리아\",\"kk\":\"Бразилиа\",\"mr\":\"ब्राझिलिया\",\"tl\":\"Brasilia\",\"ja\":\"ブラジリア\",\"yi\":\"בראזיליא\",\"en\":\"Brasília\",\"uk\":\"Бразилія\",\"hu\":\"Brazíliaváros\",\"ro\":\"Brazilia\",\"fr\":\"Brasilia\",\"eo\":\"Braziljo\",\"la\":\"Brasiliopolis\",\"ln\":\"Brazilia\",\"tr\":\"Brezilya\",\"bg\":\"Бразилия\",\"co\":\"Brasilia\",\"be\":\"Бразілія\",\"de\":\"Brasilia\",\"ay\":\"Brasilia\",\"sl\":\"Brasilia\",\"is\":\"Brasilía\",\"el\":\"Μπραζίλια\",\"eu\":\"Brasilia\",\"it\":\"Brasilia\",\"mk\":\"Бразилија\",\"mn\":\"Бразилиа\",\"bo\":\"པུ་རུ་ཟི་ལི་ཡ།\",\"pt\":\"Brasília\",\"kl\":\"Brasilia\",\"ar\":\"برازيليا\",\"fa\":\"برازیلیا\",\"nl\":\"Brasilia\",\"lt\":\"Brazilija\",\"my\":\"ဘရာစေးလေးယားမြို့\"},\"lat\":-15.7934036,\"lon\":-47.8823172,\"country\":\"BR\",\"state\":\"Federal District\"}]"

Nesse arquivo, temos o nome da cidade em várias línguas e, ao final, as informações sobre sua localização

loc_JSON <- jsonlite::fromJSON(loc_texto)

latitude <- loc_JSON$lat
longitude <- loc_JSON$lon

Transformamos a latitude e longitude obtidas em objetos que serão utilizados como parâmetros na URL da próxima requisição.

Requisição do clima atual em Brasília

O procedimento é o mesmo:

url2 <- base::paste0("https://api.openweathermap.org/data/2.5/weather?lat=", latitude, "&lon=", longitude, "&appid=", key, "&units=metric")
#Por default, esta API retorna a temperatura em Kelvin. Para obter a temperatura em graus Celsius, utilizamos o parâmetro "units=metric"

dados <- httr::GET(url2)
dados$status_code
[1] 200
conteudo_dados <- httr::content(dados, as = "text")

conteudo_JSON <- jsonlite::fromJSON(conteudo_dados)

Obtemos a lista:

conteudo_JSON
$coord
$coord$lon
[1] -47.8823

$coord$lat
[1] -15.7934


$weather
   id   main      description icon
1 802 Clouds scattered clouds  03n

$base
[1] "stations"

$main
$main$temp
[1] 15.78

$main$feels_like
[1] 15.42

$main$temp_min
[1] 13.38

$main$temp_max
[1] 15.78

$main$pressure
[1] 1021

$main$humidity
[1] 77


$visibility
[1] 10000

$wind
$wind$speed
[1] 0.51

$wind$deg
[1] 0


$clouds
$clouds$all
[1] 40


$dt
[1] 1719218528

$sys
$sys$type
[1] 1

$sys$id
[1] 8336

$sys$country
[1] "BR"

$sys$sunrise
[1] 1719221899

$sys$sunset
[1] 1719262179


$timezone
[1] -10800

$id
[1] 3461936

$name
[1] "Guará"

$cod
[1] 200

conteudo_JSON[["main"]][["temp"]]
[1] 15.78

Sugestões de API’s públicas

Referências